#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>

// 随机睡眠一段时间
void sleep_random(int t) {
    sleep((int)(t * (rand() / (RAND_MAX * 1.0))));
}

void delay() {
    int i = 10000000;
    while (i--)
        ;
}

#define N 5
sem_t chopstick[N];

// 哲学家就餐的线程函数
void *phi(void *id) {
    int i, myid = *(int *)id;

    // 按照资源顺序分配，总是先获取序号小的筷子
    int first_chopstick = myid % N;
    int second_chopstick = (myid + 1) % N;

    if (first_chopstick > second_chopstick) {
        // 交换，保证先获取序号小的筷子
        int temp = first_chopstick;
        first_chopstick = second_chopstick;
        second_chopstick = temp;
    }

    for (i = 0; i < 3; i++) {
        printf("phi #%d: start of thinking\n", myid);

        // 获取序号小的筷子
        sem_wait(&chopstick[first_chopstick]);
        delay();

        // 获取序号大的筷子
        sem_wait(&chopstick[second_chopstick]);

        printf("phi #%d: start of eating\n", myid);
        sleep_random(3);

        sem_post(&chopstick[first_chopstick]);
        sem_post(&chopstick[second_chopstick]);
        printf("phi #%d: end of eating\n", myid);
    }

    pthread_exit(NULL);
}

int main() {
    int i, id[N];
    pthread_t t[N];

    srand((int)time(0));

    for (i = 0; i < N; i++) {
        id[i] = i + 1;
        sem_init(&chopstick[i], 0, 1);
    }

    for (i = 0; i < N; i++)
        pthread_create(&t[i], NULL, phi, &id[i]);

    for (i = 0; i < N; i++)
        pthread_join(t[i], NULL);

    return 0;
}
